<template>
  <div class="my-image-cropper">
    <div class="image-upload">
      <el-dialog
          :model-value="imageUploadShow" @close="cancel"
          :title="title" :style="'width:' + width / pxToRem +'rem'">
        <el-upload
            class="upload-demo" drag multiple
            action="#"
            :http-request="() => {}"
            :before-upload="beforeUpload"
            :show-file-list="false">
          <el-icon class="el-icon--upload">
            <upload-filled/>
          </el-icon>
          <div class="el-upload__text">
            Drop file here or <em>click to upload</em>
          </div>
          <template #tip>
            <div class="el-upload__tip">
              图片大小不能超过{{ maxSize }}M
            </div>
          </template>
        </el-upload>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="cancel()">关 闭</el-button>
          </div>
        </template>
      </el-dialog>
    </div>
    <div class="image-cropper" style="height: 1rem">
      <el-dialog
          :model-value="imageCropperShow"
          :width="cropperDialogWidth"
          @close="imageCropperShow = false"
          title="裁剪图片">
        <div class="image-cropper-main">
          <div class="image-cropper-main-top">
            <div class="cropper" :style="cropperHAndW">
              <vue-cropper
                  ref="cropper"
                  :img="options.img"
                  :output-size="options.outputSize"
                  :outputType="options.outputType"
                  :info="options.info"
                  :can-scale="options.canScale"
                  :autoCrop="options.autoCrop"
                  :fixed="options.fixed"
                  :fixed-number="options.fixedNumber"
                  :full="options.full"
                  :can-move="options.canMove"
                  :can-move-box="options.canMoveBox"
                  :original="options.original"
                  :center="options.center"
                  :high="options.high"
                  :info-true="options.infoTrue"
                  :fixedBox="options.fixedBox"
                  :autoCropWidth="options.autoCropWidth"
                  :autoCropHeight="options.autoCropHeight"
                  :maxImgSize="options.maxImgSize"
                  :enlarge="options.enlarge"
                  :mode="options.mode"
                  :limit-min-size="options.limitMinSize"
                  :fill-color="options.fillColor"
                  @realTime="realTime"
                  @imgMoving="imgMoving"
                  @cropMoving="cropMoving"
                  @imgLoad="imgLoad"/>
            </div>
            <div class="image-show" :style="previewH">
              <div class="title">
                预览
              </div>
              <div class="title-content">
                <template v-if="shape==='square'">
                  <div class="shape-square" :style="squareHAndW">
                    <div class="shape-item">
                      <img :src="previewImgUrl" alt="square"/>
                    </div>
                  </div>
                </template>
                <template v-else-if="shape==='circle'">
                  <div class="shape-circle" :style="circleHAndW">
                    <div class="shape-item">
                      <img :src="previewImgUrl" alt="circle"/>
                    </div>
                  </div>
                </template>
                <template v-else>
                  <div class="shape-square" :style="squareHAndW">
                    <div class="shape-item">
                      <img :src="previewImgUrl" alt="square"/>
                    </div>
                  </div>
                  <div class="shape-circle" :style="circleHAndW">
                    <div class="shape-item">
                      <img :src="previewImgUrl" alt="circle"/>
                    </div>
                  </div>
                </template>
              </div>
            </div>
          </div>
          <div class="image-cropper-main-footer">
            <div class="left">
              <el-button @click="returnUploadPic">重选图片</el-button>
              <el-button @click="this.$refs.cropper.rotateRight()">左旋转</el-button>
              <el-button @click=" this.$refs.cropper.rotateLeft()">右旋转</el-button>
            </div>
            <div class="right">
              <el-button @click="uploadImage">上 传</el-button>
            </div>
          </div>
        </div>
      </el-dialog>
    </div>
  </div>
</template>

<script>
// npm install vue-cropper@next + vue.3x
import {UploadFilled} from '@element-plus/icons-vue'
import {ElMessage} from "element-plus";
import {VueCropper} from "vue-cropper";
import "vue-cropper/dist/index.css";
import axios from "axios";
import {successCode} from "@/api/base/http.js";

export default {
  components: {
    VueCropper,
    UploadFilled: UploadFilled,
  },
  props: {
    imageUploadShow: {
      type: Boolean,
      default: false
    },
    action: {//图片上传路径
      type: String,
      required: true,
      default: "/_api/portal/image"
    },
    name: {//图片上传参数名，默认image
      type: String,
      default: "file"
    },
    title: {
      type: String,
      default: "上传图片"
    },
    width: { //上传图片的dialog宽度 高度自适应
      type: Number,
      default: 600
    },
    maxSize: {//图片最大内存  MB单位
      type: Number,
      default: 10
    },
    shape: {
      type: String,
      default: "all" //all square circle
    },
    pxToRem: {
      type: Number,
      default: 16 //all square circle
    },
    cropperOptions: {//裁剪图片的配置，传入对象，参数随机配置，如果没有，则使用默认
      type: Object,
      default: {
        img: null,//裁剪图片的地址	 默认空	(url 地址, base64, blob)
        outputSize: 1,//裁剪生成图片的质量 默认1  0.1 ~ 1
        outputType: 'png',//裁剪生成图片的格式 默认jpg (jpg 需要传入jpeg)   (jpeg, png, webp)
        info: true,//裁剪框的大小信息 默认true
        canScale: true,//图片是否允许滚轮缩放 默认true
        autoCrop: true,//是否默认生成截图框 默认false
        fixed: false,//是否开启截图框宽高固定比例 默认false
        fixedNumber: [1, 1],//截图框的宽高比例, 开启fixed生效 默认[1, 1]  ([ 宽度 , 高度 ])
        full: false,//是否输出原图比例的截图, 默认false
        canMove: true,//上传图片是否可以移动, 默认true
        canMoveBox: false,//截图框能否拖动, 默认true
        original: false,//上传图片按照原始比例渲染, 默认false
        centerBox: false,//截图框是否被限制在图片里面 默认false
        high: true,//是否按照设备的dpr输出等比例图片 默认true
        infoTrue: false,//true 为展示真实输出图片宽高 默认false 展示看到的截图框宽高
        fixedBox: true,//固定截图框大小, 不允许改变 默认false false
        autoCropWidth: 300,//默认生成截图框宽度 默认容器的80%  (0 ~ max)
        autoCropHeight: 200,//默认生成截图框高度 默认容器的80%  (0 ~ max)
        maxImgSize: 600,//限制图片最大宽度和高度  默认2000  ( 0 ~ max)
        enlarge: 1,//图片根据截图框输出比例倍数  默认1    (0 ~ max(建议不要太大不然会卡死的呢))
        mode: "contain",//图片默认渲染方式  默认contain  （contain , cover, 100px, 100% auto）
        limitMinSize: 10,//裁剪框限制最小区域  默认10   (Number, Array, String)
        fillColor: null,//导出时背景颜色填充  默认空  ( #ffffff, white)}
      }
    },
  },
  emits: ["update:imageUploadShow", "upload"],
  data() {
    return {
      imageCropperShow: false,
      options: {
        img: null,//裁剪图片的地址	 默认空	(url 地址, base64, blob)
        outputSize: 1,//裁剪生成图片的质量 默认1  0.1 ~ 1
        outputType: 'png',//裁剪生成图片的格式 默认jpg (jpg 需要传入jpeg)   (jpeg, png, webp)
        info: true,//裁剪框的大小信息 默认true
        canScale: true,//图片是否允许滚轮缩放 默认true
        autoCrop: true,//是否默认生成截图框 默认false
        fixed: false,//是否开启截图框宽高固定比例 默认false
        fixedNumber: [1, 1],//截图框的宽高比例, 开启fixed生效 默认[1, 1]  ([ 宽度 , 高度 ])
        full: false,//是否输出原图比例的截图, 默认false
        canMove: true,//上传图片是否可以移动, 默认true
        canMoveBox: true,//截图框能否拖动, 默认true
        original: false,//上传图片按照原始比例渲染, 默认false
        centerBox: false,//截图框是否被限制在图片里面 默认false
        high: true,//是否按照设备的dpr输出等比例图片 默认true
        infoTrue: false,//true 为展示真实输出图片宽高 默认false 展示看到的截图框宽高
        fixedBox: false,//固定截图框大小, 不允许改变 默认false false
        autoCropWidth: 300,//默认生成截图框宽度 默认容器的80%  (0 ~ max)
        autoCropHeight: 200,//默认生成截图框高度 默认容器的80%  (0 ~ max)
        maxImgSize: 600,//限制图片最大宽度和高度  默认2000  ( 0 ~ max)
        enlarge: 1,//图片根据截图框输出比例倍数  默认1    (0 ~ max(建议不要太大不然会卡死的呢))
        mode: "contain",//图片默认渲染方式  默认contain  （contain , cover, 100px, 100% auto）
        limitMinSize: 10,//裁剪框限制最小区域  默认10   (Number, Array, String)
        fillColor: null,//导出时背景颜色填充  默认空  ( #ffffff, white)
      },
      previewImgUrl: "",
      imageMsg: {
        name: "image.jpg",
        type: 'image/jpeg',
      }
    }
  },
  mounted() {
    this.initOptions(this.cropperOptions);
  },
  watch: {
    "cropperOptions": {
      handler(newVal) {
        this.initOptions(newVal);
      }
    }
  },
  computed: {
    cropperDialogWidth()  {
      let result = this.width;
      if (this.width <= 500) {
        result = this.width * 2;
      } else if (this.width <= 1000) {
        result = this.width * 1.5;
      } else {
        result = this.width;
      }
      return result;
    },
    previewH() {
      let a = 2;
      return 'height: ' + this.options.autoCropHeight * a / this.pxToRem + 'rem;';
    },
    cropperHAndW() {
      let a = 2;
      return 'height: ' + this.options.autoCropHeight * a / this.pxToRem + 'rem;width: ' + this.options.autoCropWidth * a / this.pxToRem + 'rem;';
    },
    circleHAndW() {
      let a = 1;
      let size = this.options.autoCropHeight < this.options.autoCropWidth ? this.options.autoCropHeight : this.options.autoCropWidth;
      return 'height: ' + size * a / this.pxToRem + 'rem;width: ' + size * a / this.pxToRem + 'rem;';
    },
    squareHAndW() {
      let a = 1;
      return 'height: ' + this.options.autoCropHeight * a / this.pxToRem + 'rem;width: ' + this.options.autoCropWidth * a / this.pxToRem + 'rem;';
    }
  },
  methods: {
    test() {//注释

      // this.$refs.cropper.startCrop()	开始截图
      // this.$refs.cropper.stopCrop()	停止截图
      // this.$refs.cropper.clearCrop()	清除截图
      // this.$refs.cropper.changeScale()	修改图片大小 正数为变大 负数变小
      // this.$refs.cropper.getImgAxis()	获取图片基于容器的坐标点
      // this.$refs.cropper.getCropAxis()	获取截图框基于容器的坐标点
      // this.$refs.cropper.goAutoCrop	自动生成截图框函数
      // this.$refs.cropper.rotateRight()	向右边旋转90度
      // this.$refs.cropper.rotateLeft()	向左边旋转90度

      // this.$refs.cropper.cropW	截图框宽度
      // this.$refs.cropper.cropH	截图框高度

      // this.$refs.cropper.getCropData(data => {//获取截图的 base64 数据
      //   console.log(data)
      // })
      // this.$refs.cropper.getCropBlob(data => { //获取截图的 blob 数据
      //   console.log(data)
      // }
    },
    initOptions(newOptions) {
      // if (this.itemNotNull(newOptions.img)) {
      //   this.options.img = newOptions.img;
      // }

      if (this.itemNotNull(newOptions.outputSize)) {
        this.options.outputSize = newOptions.outputSize;
      }

      if (this.itemNotNull(newOptions.outputType)) {
        this.options.outputType = newOptions.outputType;
      }

      if (this.itemNotNull(newOptions.info)) {
        this.options.info = newOptions.info;
      }

      if (this.itemNotNull(newOptions.canScale)) {
        this.options.canScale = newOptions.canScale;
      }

      if (this.itemNotNull(newOptions.autoCrop)) {
        this.options.autoCrop = newOptions.autoCrop;
      }

      if (this.itemNotNull(newOptions.fixed)) {
        this.options.fixed = newOptions.fixed;
      }

      if (this.itemNotNull(newOptions.fixedNumber)) {
        this.options.fixedNumber = newOptions.fixedNumber;
      }

      if (this.itemNotNull(newOptions.full)) {
        this.options.full = newOptions.full;
      }

      if (this.itemNotNull(newOptions.canMove)) {
        this.options.canMove = newOptions.canMove;
      }

      if (this.itemNotNull(newOptions.canMoveBox)) {
        this.options.canMoveBox = newOptions.canMoveBox;
      }

      if (this.itemNotNull(newOptions.original)) {
        this.options.original = newOptions.original;
      }

      if (this.itemNotNull(newOptions.centerBox)) {
        this.options.centerBox = newOptions.centerBox;
      }

      if (this.itemNotNull(newOptions.high)) {
        this.options.high = newOptions.high;
      }

      if (this.itemNotNull(newOptions.infoTrue)) {
        this.options.infoTrue = newOptions.infoTrue;
      }

      if (this.itemNotNull(newOptions.fixedBox)) {
        this.options.fixedBox = newOptions.fixedBox;
      }

      if (this.itemNotNull(newOptions.autoCropWidth)) {
        this.options.autoCropWidth = newOptions.autoCropWidth;
      }

      if (this.itemNotNull(newOptions.autoCropHeight)) {
        this.options.autoCropHeight = newOptions.autoCropHeight;
      }

      if (this.itemNotNull(newOptions.maxImgSize)) {
        this.options.maxImgSize = newOptions.maxImgSize;
      }

      if (this.itemNotNull(newOptions.enlarge)) {
        this.options.enlarge = newOptions.enlarge;
      }

      if (this.itemNotNull(newOptions.mode)) {
        this.options.mode = newOptions.mode;
      }

      if (this.itemNotNull(newOptions.limitMinSize)) {
        this.options.limitMinSize = newOptions.limitMinSize;
      }

      if (newOptions.fillColor !== undefined) {
        this.options.fillColor = newOptions.fillColor;
      }
    },
    itemNotNull(item) {
      return !(item === '' || item === null || item === undefined);
    },
    uploadImage() {
      this.$refs.cropper.getCropBlob(blobData => { //获取截图的 blob 数据
        const file = new File([blobData], this.imageMsg.name, {type: this.imageMsg.type});
        const requestData = {
          [this.name]: file // 根据实际需要的字段名设置
        };
        axios.create().post(this.action, requestData, {
          headers: {'content-type': 'multipart/form-data'}
        }).then(res => {
          let resData = res.data;
          if (resData.code === successCode) {//图片上传成功
            this.$emit("upload", {"url": res.data.data, "blob": blobData});
            ElMessage.success("图片上传成功");
            this.cancel();
          } else {
            this.$refs.cropper.getCropData(data => {
              this.$emit("upload", {"url": null, "blob": data});
            })
            ElMessage.error("图片上传失败，请稍后重试")
          }
        })
      })


      // this.cancel();
    },
    realTime() {//实时预览事件
      this.$refs.cropper.getCropData(data => { //获取截图的 blob 数据
        this.previewImgUrl = data;
      })
    },
    imgMoving() {//图片移动回调函数
    },
    cropMoving() {//截图框移动回调函数

    },
    imgLoad() {//图片加载的回调, 返回结果 success, error

    },
    returnUploadPic() {
      this.$emit("update:imageUploadShow", true);
      this.imageCropperShow = false;
    },
    beforeUpload(rawFile) {
      if (rawFile.type.indexOf("image/") === -1) {
        ElMessage.error("请上传图片类型文件");
        return false;
      }
      if (rawFile.size / 1024 / 1024 > this.maxSize) {
        ElMessage.error("文件大小不能超过" + this.maxSize + "MB");
        return false;
      }
      const reader = new FileReader();
      reader.readAsDataURL(rawFile);
      reader.onload = () => {
        this.options.img = reader.result;
        this.cancel();
        this.imageCropperShow = true;
      };
      this.imageMsg.name = rawFile.name;
      this.imageMsg.type = rawFile.type;
    },
    cancel() {
      this.$emit("update:imageUploadShow", false);
    }
  }
}
</script>

<style lang="scss" scoped>
.my-image-cropper {
  .image-cropper {
    .image-cropper-main {

      .image-cropper-main-top {
        display: flex;
        align-items: center;
        justify-content: space-around;

        .cropper {
          user-select: none;
        }

        .title {
          font-size: 2rem;
          font-weight: bold;
        }

        .title-content {
          display: flex;
          align-items: center;
          justify-content: space-around;
          user-select: none;
        }

        .image-show {
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: space-around;
          height: 100%;
          user-select: none;

          .shape-circle {
            margin-left: 2rem;
            border-radius: 50%;
            padding: .2rem;
            border: 0.2rem dashed #409EFF;
            overflow: hidden;

            .shape-item {
              width: 100%;
              height: 100%;
              border-radius: 50%;
              overflow: hidden;
            }
          }

          .shape-square {
            margin-right: 2rem;
            padding: .2rem;
            border: 0.2rem dashed #409EFF;
            overflow: hidden;

            .shape-item {
              width: 100%;
              height: 100%;
              overflow: hidden;
            }
          }

          img {
            user-select: none;
          }
        }
      }

      .image-cropper-main-footer {
        display: flex;
        align-items: center;
        justify-content: space-around;
        margin: 1rem 0;
      }
    }
  }
}

</style>
